

#include "asw/include/drv_api.h"
#include "asw/include/drv_io.h"
#include "dal.h"

extern dal_op_t g_dal_op;

#define DRV_ACL_MASK_OFFSET 0x20
typedef struct blk_info_s
{
   uint32 addr_base;
   uint16 cpu_acc_req_id;
   uint16 cpu_acc_wdata_id;
   uint16 cpu_acc_rdata_id;
   uint16 cpu_acc_rfield_id;
} blk_info_t;

#ifndef MEM_MODEL
blk_info_t   g_blk_info[] =
{
    {DmaRegBlk_base,0,0,0,0},
    {GlobalRegBlk_base,0,0,0,0},
    {IntfRegBlk_base,0,0,0,0},
    {MibMemBlk_base,0,0,0,0},
    {MibRegBlk_base,0,0,0,0},
    {MmuRegBlk_base,MmuCpuAccessReq_t,MmuCpuAccessWdata_t,MmuCpuAccessRdata_t,MmuCpuAccessRdata_data_f},
    {MmuRegBlk_base,MmuCpuAccessReq_t,MmuCpuAccessWdata_t,MmuCpuAccessRdata_t,MmuCpuAccessRdata_data_f},
    {QosRegBlk_base,QosCpuAccessReq_t,QosCpuAccessWdata_t,QosCpuAccessRdata_t,QosCpuAccessRdata_data_f},
    {QosRegBlk_base,QosCpuAccessReq_t,QosCpuAccessWdata_t,QosCpuAccessRdata_t,QosCpuAccessRdata_data_f},
    {PeRegBlk_base,PeCpuAccessReq_t,PeCpuAccessWdata_t,PeCpuAccessRdata_t,PeCpuAccessRdata_data_f},
    {PeRegBlk_base,PeCpuAccessReq_t,PeCpuAccessWdata_t,PeCpuAccessRdata_t,PeCpuAccessRdata_data_f},
    {AclMemBlk_base,0,0,0,0},
    {ArlMemBlk_base,ArlCpuAccessReq_t,ArlCpuAccessWdata_t,ArlCpuAccessRdata_t,ArlCpuAccessRdata_data_f},
    {ArlRegBlk_base,ArlCpuAccessReq_t,ArlCpuAccessWdata_t,ArlCpuAccessRdata_t,ArlCpuAccessRdata_data_f},
    {FxPcs_base,0,0,0,0},
    {QsgmiiPcs_base,0,0,0,0},
    {SgmiiPcs_base,0,0,0,0},
    {Gpio_base,0,0,0,0},
    {Led_base,0,0,0,0},
    {Mdio_base,0,0,0,0},
    {Qspi_base,0,0,0,0},
    {Sup_base,0,0,0,0}
#if 0
    {TimerSoc_base,0,0,0,0},
    {WdtSoc_base,0,0,0,0},
    {SupEfuse_base,0,0,0,0}
#endif
};
#else
blk_info_t   g_blk_info[25] = {{0, 0, 0, 0, 0}};
#endif

#ifdef MEM_MODEL
#define HASH_MIX(a, b, c)        \
    {                                         \
        a -= b; a -= c; a ^= (c >> 13);           \
        b -= c; b -= a; b ^= (a << 8);            \
        c -= a; c -= b; c ^= (b >> 13);           \
        a -= b; a -= c; a ^= (c >> 12);           \
        b -= c; b -= a; b ^= (a << 16);           \
        c -= a; c -= b; c ^= (b >> 5);            \
        a -= b; a -= c; a ^= (c >> 3);            \
        b -= c; b -= a; b ^= (a << 10);           \
        c -= a; c -= b; c ^= (b >> 15);           \
    }                                         \

uint32
drv_asw_hash_caculate(uint32 size, void* kk)
{
    uint32 len = 0;
    uint32 a = 0x9e3779b9;
    uint32 b = 0x9e3779b9;
    uint32 c = 0;
    uint8* h = (uint8*) kk;

    len = size;

    while (len >= 12)
    {
        a += (h[0] + ((uint32)h[1] << 8) + ((uint32)h[2] << 16) + ((uint32)h[3] << 24));
        b += (h[4] + ((uint32)h[5] << 8) + ((uint32)h[6] << 16) + ((uint32)h[7] << 24));
        c += (h[8] + ((uint32)h[9] << 8) + ((uint32)h[10] << 16) + ((uint32)h[11] << 24));
        HASH_MIX(a, b, c);
        h += 12;
        len -= 12;
    }
    c += size;

    while (len >= 1)
    {
        if (9 <= len)
        {
            c += ((uint32)h[len-1] << ((len-8)*8));
        }
        else if ( len >= 5 && len <= 8)
        {
            b += ((uint32)h[len-1] << ((len-5)*8));
        }
        else
        {
            a += ((uint32)h[len-1] << ((len-1)*8));
        }
        len--;
    }
    HASH_MIX(a, b, c);

    return c;
}
#endif

int32
drv_asw_chip_write(uint8 lchip, addrs_t offset, uint32* p_value, uint32 len)
{
    if(p_asw_drv_master->model_en)
    {
        sal_memcpy((uint8*)(uintptr)offset,(uint8*)p_value,len);
    }
    else
    {
        g_dal_op.smi_write(lchip, offset, len, p_value);
    }
    return 0;
}
int32
drv_asw_chip_read(uint8 lchip, addrs_t offset, uint32* p_value, uint32 len)
{
    if(p_asw_drv_master->model_en)
    {
        sal_memcpy((uint8*)p_value,(uint8*)(uintptr)offset,len);
    }
    else
    {
        g_dal_op.smi_read(lchip, offset, len, p_value);
    }
    return 0;
}
int32
_drv_asw_chip_sram_tbl_write(uint8 lchip, uint32 tbl_id, uint32 index, uint32* data)
{
    int32 ret;
    addrs_t start_data_addr = 0;
    const tables_info_t *ptbl;
    uint8  addr_offset = 0;

    ptbl = &drv_tbls_list[tbl_id];
    if (TABLE_ADDR_NUM(lchip, tbl_id) > 1)
    {
         uint32 entry_offset = 0;
         entry_offset = TABLE_MAX_INDEX(lchip, tbl_id)/ TABLE_ADDR_NUM(lchip, tbl_id);
         addr_offset = index / entry_offset;
         index = index%entry_offset;
    }
    else
    {
        addr_offset = 0;
    }
    start_data_addr = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[addr_offset] + index * ptbl->entry_offset;

    ret = drv_asw_chip_write(lchip, start_data_addr, data, ptbl->entry_size);
    if (ret < 0)
    {
        return ret;
    }

    return DRV_E_NONE;
}

/**
 @brief The function read table data from a sram memory location
*/
int32
_drv_asw_chip_sram_tbl_read(uint8 lchip, uint32 tbl_id, uint32 index, uint32* data)
{
    int32 ret;
    const tables_info_t *ptbl;
    addrs_t start_data_addr = 0;
    uint8  addr_offset = 0;
    uint32 entry_offset = 0;

    ptbl = &drv_tbls_list[tbl_id];
    if (TABLE_ADDR_NUM(lchip, tbl_id) > 1)
    {
         entry_offset = TABLE_MAX_INDEX(lchip, tbl_id)/ TABLE_ADDR_NUM(lchip, tbl_id);
         addr_offset = index / entry_offset;
         index = index%entry_offset;
    }
    else
    {
        addr_offset = 0;
    }
    start_data_addr = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[addr_offset] + index * ptbl->entry_offset;

    ret = drv_asw_chip_read(lchip, start_data_addr, data, ptbl->entry_size);
    if (ret < 0)
    {
        return ret;
    }
    return DRV_E_NONE;
}

/**
 @brief The function write table data to a sram memory location
*/
int32
drv_asw_chip_sram_tbl_write(uint8 lchip, uint32 tbl_id, uint32 index, uint32* data)
{
    int32 ret = DRV_E_NONE;
    const tables_info_t *ptbl;

    if(p_asw_drv_master->io_wr_dis[lchip])
    {
        return DRV_E_NONE;
    }

    ptbl = &drv_tbls_list[tbl_id];
    if(ptbl->op_type == OP_INDIRECT && !p_asw_drv_master->model_en)
    {
        uint32 req_tbl_id = g_blk_info[ptbl->blk_id].cpu_acc_req_id;
        uint32 wdata_tbl_id = g_blk_info[ptbl->blk_id].cpu_acc_wdata_id;
        PeCpuAccessReq_m req;
        PeCpuAccessWdata_m wdata;
        addrs_t start_data_addr = 0;

        if(ptbl->tbl_type == TBL_HASH)
        {
            drv_asw_chip_hash_write(lchip, tbl_id, index, data);
            return DRV_E_NONE;
        }
        start_data_addr = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * ptbl->entry_offset;

        DRV_LOCK(lchip);
        /*1.write  data to buffer */
        sal_memcpy(&wdata,data,ptbl->entry_size);
        ret = _drv_asw_chip_sram_tbl_write( lchip, wdata_tbl_id, 0, (uint32*)&wdata);

        /*2. triger   write */
        SetPeCpuAccessReq(V,req_f,&req,1);
        SetPeCpuAccessReq(V,reqType_f,&req,1);//write
        SetPeCpuAccessReq(V,page_f,&req,0);
        SetPeCpuAccessReq(V,addr_f,&req,start_data_addr);
        ret =ret?ret:_drv_asw_chip_sram_tbl_write( lchip, req_tbl_id, 0, (uint32*)&req);
        DRV_UNLOCK(lchip);
    }
    else
    {
        DRV_LOCK(lchip);
            ret = _drv_asw_chip_sram_tbl_write( lchip, tbl_id, index, data);
        DRV_UNLOCK(lchip);
    }
    return ret;
}

/**
 @brief The function read table data from a sram memory location
*/
int32
drv_asw_chip_sram_tbl_read(uint8 lchip, uint32 tbl_id, uint32 index, uint32* data)
{
    int32 ret;
    const tables_info_t *ptbl;
    uint32 timeout = 30;

    ptbl = &drv_tbls_list[tbl_id];
    if(ptbl->op_type == OP_INDIRECT && !p_asw_drv_master->model_en)
    {
        uint32 req_tbl_id = g_blk_info[ptbl->blk_id].cpu_acc_req_id;
        uint32 rdata_tbl_id = g_blk_info[ptbl->blk_id].cpu_acc_rdata_id;
        ds_t ds;
        addrs_t start_data_addr = 0;

        if(ptbl->tbl_type == TBL_HASH)
        {
            drv_asw_chip_hash_read(lchip, tbl_id, index, data);
            return DRV_E_NONE;
        }
        start_data_addr = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * ptbl->entry_offset;

        DRV_LOCK(lchip);
        /*1. triger   read */
        SetPeCpuAccessReq(V,req_f,&ds,1);
        SetPeCpuAccessReq(V,reqType_f,&ds,0);//read
        SetPeCpuAccessReq(V,page_f,&ds,0);
        SetPeCpuAccessReq(V,addr_f,&ds,start_data_addr);
        ret =_drv_asw_chip_sram_tbl_write(lchip, req_tbl_id, 0, (uint32*)&ds);
        if(ret < 0)
        {
            DRV_UNLOCK(lchip);
            return DRV_E_NOT_READY;
        }
        /*2.wait read from   buffer */
        do
        {
            _drv_asw_chip_sram_tbl_read( lchip, rdata_tbl_id, 0,(uint32*)&ds);
        }while(!DRV_GET_FIELD_V(lchip, rdata_tbl_id, 0, &ds)&& timeout--);
        if(!DRV_GET_FIELD_V(lchip, rdata_tbl_id, 0, &ds))
        {
            DRV_UNLOCK(lchip);
            return DRV_E_TIME_OUT;
        }
        sal_memcpy((uint8*)data,(uint8*)&ds, ptbl->entry_size);
        DRV_UNLOCK(lchip);
    }
    else
    {
        DRV_LOCK(lchip);
        _drv_asw_chip_sram_tbl_read( lchip, tbl_id, index, data);
        DRV_UNLOCK(lchip);
    }
    return DRV_E_NONE;
}

/**
 @brief The function write table data to a sram memory location
*/
int32
drv_asw_chip_hash_add(uint8 lchip, uint32 tbl_id, uint32 index, uint32* data)
{
    const tables_info_t *ptbl;
#ifndef MEM_MODEL
    uint32 timeout = 10000;
#endif
    int32 ret = DRV_E_NONE;
    ptbl = &drv_tbls_list[tbl_id];

    if(ptbl->tbl_type != TBL_HASH)
    {
        return DRV_E_INVALID_TBL;
    }
    if(p_asw_drv_master->io_wr_dis[lchip])
    {
        return DRV_E_NONE;
    }

    DRV_LOCK(lchip);
#ifdef MEM_MODEL
    if (p_asw_drv_master->model_en)
    {
        ds_t ds;
        uint32 index = 0;
        uint32 value = 0;

        sal_memcpy(&ds,data,ptbl->entry_size);
        if((tbl_id >=XlateMacVlanKey_t && tbl_id<=XlateIpv4Key_t) || tbl_id == VlanHashView9_t)
        {
            SetXlateMacVlanKey(V,valid_f, &ds, 0);
            SetXlateMacVlanKey(V,ivmIndex_f, &ds, 0);
        }
        else if (tbl_id >=XlateSvlanKey_t && tbl_id<=XlateItagKey_t)
        {
            SetXlateSvlanKey(V,valid_f, &ds, 0);
            SetXlateSvlanKey(V,ivmIndex_f, &ds, 0);
        }
        else if (tbl_id == XlateIpv6Key_t || tbl_id == XlateMacKey0_t)
        {
            SetXlateIpv6Key(V,valid_f, &ds, 0);
            SetXlateIpv6Key(V,ivmIndex_f, &ds, 0);
        }
        else
        {
            SetMcTable(V,dmacFilter_f, &ds, 0);
            SetMcTable(V,smacFilter_f, &ds, 0);
            SetMcTable(V,stationMoved_f, &ds, 0);
            SetMcTable(V,pendingLearn_f, &ds, 0);
            SetMcTable(V,state_f, &ds, 0);
            SetMcTable(V,mstp_f, &ds, 0);
            SetMcTable(V,portId_f, &ds, 0);
        }
        index = drv_asw_hash_caculate(ptbl->entry_size, ds)%ptbl->entry_num;
        _drv_asw_chip_sram_tbl_read(lchip, tbl_id, index, (uint32*)&ds);
        if(tbl_id >=XlateMacVlanKey_t && tbl_id<=XlateMacKey0_t)
        {
            value = GetXlateMacVlanKey(V,valid_f, &ds);
        }
        else
        {
            value = GetArlTable(V,state_f, &ds);
        }
        if (value)
        {
            ret = DRV_E_HASH_CONFLICT;
            goto out;
        }
        if (tbl_id == McTable_t)
        {
            SetMcTable(V,portId_f, data, index);
        }
        else if((tbl_id >=XlateMacVlanKey_t && tbl_id<=XlateIpv4Key_t) || tbl_id == VlanHashView9_t)
        {
            SetXlateMacVlanKey(V,ivmIndex_f, data, index);
        }
        else if (tbl_id >=XlateSvlanKey_t && tbl_id<=XlateItagKey_t)
        {
            SetXlateSvlanKey(V,ivmIndex_f, data, index);
        }
        else if (tbl_id == XlateIpv6Key_t || tbl_id == XlateMacKey0_t)
        {
            SetXlateIpv6Key(V,ivmIndex_f, &ds, index);
        }
        _drv_asw_chip_sram_tbl_write(lchip, tbl_id, index, data);
    }
#else
    if(tbl_id >=XlateMacVlanKey_t && tbl_id<=XlateMacKey0_t)
    {
        PeCpuAccessHashReq_m acc_req;
        PeCpuAccessHashWdata_m acc_data;
        PeCpuAccessHashStatus_m acc_status;
        PeCpuAccessHashAddr_m acc_addr;
        uint8 key_type = 0;
        /*1. reset  hash write */
        SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,0);
        SetPeCpuAccessHashReq(V,searchType_f,&acc_req,0);//write by key if exist it will not overwrite
        SetPeCpuAccessHashReq(V,directAddr_f,&acc_req,0);
        key_type = DRV_GET_FIELD_V(lchip, tbl_id, (((XlateMacKey_t == tbl_id) || (XlateIpv6Key_t == tbl_id))?3:4), data);
        SetPeCpuAccessHashReq(V,keyType_f,&acc_req,key_type);
        _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

        /*2.write hash data to buffer */
        sal_memcpy((uint8*)&acc_data,(uint8*)data,ptbl->entry_size);
        _drv_asw_chip_sram_tbl_write( lchip, PeCpuAccessHashWdata_t, 0,(uint32*) &acc_data);

        /*3. triger  hash write */
        SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,1);
        _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

        /*4. wait status */
        do
        {
            _drv_asw_chip_sram_tbl_read(lchip,  PeCpuAccessHashStatus_t, 0,(uint32*)&acc_status);
        }while(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status) && timeout--);

        if(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status))
        {
            ret = DRV_E_TIME_OUT;
            goto out;
        }
        if(GetPeCpuAccessHashStatus(V,hitMiss_f,&acc_status))
        {
            ret = DRV_E_EXIST;
            goto out;
        }
        _drv_asw_chip_sram_tbl_read(lchip,  PeCpuAccessHashAddr_t, 0,(uint32*)&acc_addr);
        index = GetPeCpuAccessHashAddr(V,tablePtr_f,&acc_addr);
        DRV_SET_FIELD_V(lchip, tbl_id, 0, data, index);

        SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,0);
        SetPeCpuAccessHashReq(V,searchType_f,&acc_req,1);//write by key if exist it will overwrite
        SetPeCpuAccessHashReq(V,directAddr_f,&acc_req,0);
        SetPeCpuAccessHashReq(V,keyType_f,&acc_req,key_type);
        _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

        /*2.write hash data to buffer */
        sal_memcpy((uint8*)&acc_data,(uint8*)data,ptbl->entry_size);
        _drv_asw_chip_sram_tbl_write( lchip, PeCpuAccessHashWdata_t, 0,(uint32*) &acc_data);

        /*3. triger  hash write */
        SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,1);
        _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

        /*4. wait status */
        do
        {
            _drv_asw_chip_sram_tbl_read(lchip, PeCpuAccessHashStatus_t, 0,(uint32*)&acc_status);
        }while(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status) && timeout--);

        if(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status))
        {
            ret = DRV_E_TIME_OUT;
            goto out;
        }
        if(!GetPeCpuAccessHashStatus(V,learned_f,&acc_status))
        {
            ret = DRV_E_HASH_CONFLICT;
            goto out;
        }
    }
    else if(tbl_id ==ArlTable_t|| tbl_id==McTable_t)
    {
        CpuSearchCtrl_m acc_req;
        CpuSearchStatus_m acc_status;
        CpuSearchAddr_m acc_addr;

        /*1. reset  hash write */
        SetCpuSearchCtrl(V,searchMc_f,&acc_req,(tbl_id ==ArlTable_t)?0:1);
        SetCpuSearchCtrl(V,searchStart_f,&acc_req,0);
        SetCpuSearchCtrl(V,searchType_f,&acc_req,(tbl_id ==ArlTable_t)?1:0);//write by key if exist it will overwrite
        SetCpuSearchCtrl(V,directAddr_f,&acc_req,0);
        _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

        /*2.write hash data to buffer */
        _drv_asw_chip_sram_tbl_write( lchip, CpuUpdateEntry_t, 0, data);

        /*3. triger  hash write */
        SetCpuSearchCtrl(V,searchStart_f,&acc_req,1);
        _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

        /*4. wait status */
        do
        {
            _drv_asw_chip_sram_tbl_read(lchip,  CpuSearchStatus_t, 0,(uint32*)&acc_status);
        }while(!GetCpuSearchStatus(V,searchDone_f,&acc_status) && timeout--);

        if(!GetCpuSearchStatus(V,searchDone_f,&acc_status))
        {
            ret = DRV_E_TIME_OUT;
            goto out;
        }
	    if(((tbl_id == ArlTable_t) && !GetCpuSearchStatus(V,learned_f,&acc_status))
        && ((tbl_id == McTable_t)  && GetCpuSearchStatus(V,hitMiss_f,&acc_status)))
        {
            ret = DRV_E_HASH_CONFLICT;
            goto out;
        }
        if (tbl_id == McTable_t)
        {
            _drv_asw_chip_sram_tbl_read(lchip,  CpuSearchAddr_t, 0,(uint32*)&acc_addr);
            SetMcTable(V,portId_f, data, GetCpuSearchAddr(V,tablePtr_f,&acc_addr));
            SetCpuSearchCtrl(V,searchMc_f,&acc_req,1);
            SetCpuSearchCtrl(V,searchStart_f,&acc_req,0);
            SetCpuSearchCtrl(V,searchType_f,&acc_req,1);//write by key if exist it will overwrite
            SetCpuSearchCtrl(V,directAddr_f,&acc_req,0);
            _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

            /*2.write hash data to buffer */
            _drv_asw_chip_sram_tbl_write( lchip, CpuUpdateEntry_t, 0, data);

            /*3. triger  hash write */
            SetCpuSearchCtrl(V,searchStart_f,&acc_req,1);
            _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

            /*4. wait status */
            do
            {
                _drv_asw_chip_sram_tbl_read(lchip,  CpuSearchStatus_t, 0,(uint32*)&acc_status);
            }while(!GetCpuSearchStatus(V,searchDone_f,&acc_status) && timeout--);

            if(!GetCpuSearchStatus(V,searchDone_f,&acc_status))
            {
                ret = DRV_E_TIME_OUT;
                goto out;
            }
            if(!GetCpuSearchStatus(V,learned_f,&acc_status))
            {
                ret = DRV_E_HASH_CONFLICT;
                goto out;
            }
        }
   }
#endif
out:
    DRV_UNLOCK(lchip);
    return ret;
}

/**
 @brief The function read table data from a sram memory location
*/
int32
drv_asw_chip_hash_delete(uint8 lchip, uint32 tbl_id, uint32 index, uint32* data)
{
    const tables_info_t *ptbl;
#ifndef MEM_MODEL
    uint32 timeout = 10000;
#endif
    int32 ret = DRV_E_NONE;

    ptbl = &drv_tbls_list[tbl_id];

    if(ptbl->tbl_type != TBL_HASH)
    {
        return DRV_E_INVALID_TBL;
    }

    DRV_LOCK(lchip);
#ifdef MEM_MODEL
    if (p_asw_drv_master->model_en)
    {
        ds_t ds;
        uint32 index = 0;
        uint32 value = 0;

        sal_memcpy(&ds,data,ptbl->entry_size);
        if((tbl_id >=XlateMacVlanKey_t && tbl_id<=XlateIpv4Key_t) || tbl_id == VlanHashView9_t)
        {
            SetXlateMacVlanKey(V,valid_f, &ds, 0);
            SetXlateMacVlanKey(V,ivmIndex_f, &ds, 0);
        }
        else if (tbl_id >=XlateSvlanKey_t && tbl_id<=XlateItagKey_t)
        {
            SetXlateSvlanKey(V,valid_f, &ds, 0);
            SetXlateSvlanKey(V,ivmIndex_f, &ds, 0);
        }
        else if (tbl_id == XlateIpv6Key_t || tbl_id == XlateMacKey0_t)
        {
            SetXlateIpv6Key(V,valid_f, &ds, 0);
            SetXlateIpv6Key(V,ivmIndex_f, &ds, 0);
        }
        else
        {
            SetMcTable(V,dmacFilter_f, &ds, 0);
            SetMcTable(V,smacFilter_f, &ds, 0);
            SetMcTable(V,stationMoved_f, &ds, 0);
            SetMcTable(V,pendingLearn_f, &ds, 0);
            SetMcTable(V,state_f, &ds, 0);
            SetMcTable(V,mstp_f, &ds, 0);
            SetMcTable(V,portId_f, &ds, 0);
        }
        index = drv_asw_hash_caculate(ptbl->entry_size, ds)%ptbl->entry_num;
        _drv_asw_chip_sram_tbl_read(lchip, tbl_id, index, (uint32*)&ds);
        if(tbl_id >=XlateMacVlanKey_t && tbl_id<=XlateMacKey0_t)
        {
            value = GetXlateMacVlanKey(V,valid_f, &ds);
            SetXlateMacVlanKey(V,valid_f, data, 0);
        }
        else
        {
            value = GetArlTable(V,state_f, &ds);
            SetArlTable(V,state_f, data, 0);
        }
        if (!value)
        {
            ret = DRV_E_NOT_EXIST;
            goto out;
        }
        _drv_asw_chip_sram_tbl_write(lchip, tbl_id, index, data);
    }
#else
    if(tbl_id ==ArlTable_t|| tbl_id==McTable_t)
    {
        CpuSearchCtrl_m acc_req;
        CpuSearchStatus_m acc_status;

        /*1. reset  hash write */
        SetCpuSearchCtrl(V,searchMc_f,&acc_req,(tbl_id ==ArlTable_t)?0:1);
        SetCpuSearchCtrl(V,searchStart_f,&acc_req,0);
        SetCpuSearchCtrl(V,searchType_f,&acc_req,1);//write by key if exist it will overwrite
        SetCpuSearchCtrl(V,directAddr_f,&acc_req,0);
        _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

        /*2.write hash data to buffer */
        _drv_asw_chip_sram_tbl_write( lchip, CpuUpdateEntry_t, 0, data);

        /*3. triger  hash write */
        SetCpuSearchCtrl(V,searchStart_f,&acc_req,1);
        _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

        /*4. wait status */
        do
        {
            _drv_asw_chip_sram_tbl_read(lchip,  CpuSearchStatus_t, 0,(uint32*)&acc_status);
        }while(!GetCpuSearchStatus(V,searchDone_f,&acc_status) && timeout--);

        if(!GetCpuSearchStatus(V,searchDone_f,&acc_status)
            || !GetCpuSearchStatus(V,hitMiss_f,&acc_status))
        {
            ret = DRV_E_TIME_OUT;
            goto out;
        }
    }
    else if(tbl_id >=XlateMacVlanKey_t && tbl_id<= XlateMacKey0_t )
    {
        PeCpuAccessHashReq_m acc_req;
        PeCpuAccessHashWdata_m acc_data;
        PeCpuAccessHashStatus_m acc_status;
        uint8 key_type = 0;

        /*1. reset  hash write */
        SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,0);
        SetPeCpuAccessHashReq(V,searchType_f,&acc_req,1);//write by key if exist it will overwrite
        SetPeCpuAccessHashReq(V,directAddr_f,&acc_req,0);
        key_type = DRV_GET_FIELD_V(lchip, tbl_id, (((XlateMacKey_t == tbl_id) || (XlateIpv6Key_t == tbl_id))?3:4), data);
        SetPeCpuAccessHashReq(V,keyType_f,&acc_req,key_type);
        _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

        /*2.write hash data to buffer */
        sal_memset(&acc_data, 0, sizeof(PeCpuAccessHashWdata_m));
        sal_memcpy((uint8*)&acc_data,(uint8*)data,ptbl->entry_size);
        _drv_asw_chip_sram_tbl_write( lchip, PeCpuAccessHashWdata_t, 0, (uint32*)&acc_data);

        /*3. triger  hash write */
        SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,1);
        _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

        /*4. wait status */
        do
        {
            _drv_asw_chip_sram_tbl_read(lchip,  PeCpuAccessHashStatus_t, 0,(uint32*)&acc_status);
        }while(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status) && timeout--);

        if(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status))
        {
            ret = DRV_E_TIME_OUT;
            goto out;
        }
        if(!GetPeCpuAccessHashStatus(V,hitMiss_f,&acc_status))
        {
            ret = DRV_E_NOT_EXIST;
            goto out;
        }
    }
#endif
out:
    DRV_UNLOCK(lchip);
    return ret;
}

int32
drv_asw_chip_hash_lookup(uint8 lchip, uint32 tbl_id,  uint32 index,uint32* data)
{
    const tables_info_t *ptbl;
#ifndef MEM_MODEL
    uint32 timeout = 10000;
#endif
    int32 ret = DRV_E_NONE;

    ptbl = &drv_tbls_list[tbl_id];

    if(ptbl->tbl_type != TBL_HASH)
    {
        return DRV_E_INVALID_TBL;
    }
    DRV_LOCK(lchip);
#ifdef MEM_MODEL
    if (p_asw_drv_master->model_en)
    {
        ds_t ds;
        uint32 index = 0;

        sal_memcpy(&ds,data,ptbl->entry_size);
        if((tbl_id >=XlateMacVlanKey_t && tbl_id<=XlateIpv4Key_t) || tbl_id == VlanHashView9_t)
        {
            SetXlateMacVlanKey(V,valid_f, &ds, 0);
            SetXlateMacVlanKey(V,ivmIndex_f, &ds, 0);
        }
        else if (tbl_id >=XlateSvlanKey_t && tbl_id<=XlateItagKey_t)
        {
            SetXlateSvlanKey(V,valid_f, &ds, 0);
            SetXlateSvlanKey(V,ivmIndex_f, &ds, 0);
        }
        else if (tbl_id == XlateIpv6Key_t || tbl_id == XlateMacKey0_t)
        {
            SetXlateIpv6Key(V,valid_f, &ds, 0);
            SetXlateIpv6Key(V,ivmIndex_f, &ds, 0);
        }
        else
        {
            SetMcTable(V,dmacFilter_f, &ds, 0);
            SetMcTable(V,smacFilter_f, &ds, 0);
            SetMcTable(V,stationMoved_f, &ds, 0);
            SetMcTable(V,pendingLearn_f, &ds, 0);
            SetMcTable(V,state_f, &ds, 0);
            SetMcTable(V,mstp_f, &ds, 0);
            SetMcTable(V,portId_f, &ds, 0);
        }
        index = drv_asw_hash_caculate(ptbl->entry_size, ds)%ptbl->entry_num;
        _drv_asw_chip_sram_tbl_read(lchip, tbl_id, index, data);
    }
#else
    if(tbl_id >=XlateMacVlanKey_t && tbl_id <= XlateMacKey0_t )
    {
        PeCpuAccessHashReq_m acc_req;
        PeCpuAccessHashWdata_m acc_data;
        PeCpuAccessHashStatus_m acc_status;
        PeCpuAccessHashRdata_m  acc_rdata;
        uint8 key_type = 0;

        /*1. reset  hash read */
        SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,0);
        SetPeCpuAccessHashReq(V,searchType_f,&acc_req,0);//lookup by key
        SetPeCpuAccessHashReq(V,directAddr_f,&acc_req,0);
        key_type = DRV_GET_FIELD_V(lchip, tbl_id, (((XlateMacKey_t == tbl_id) || (XlateIpv6Key_t == tbl_id))?3:4), data);
        SetPeCpuAccessHashReq(V,keyType_f,&acc_req,key_type);
        _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

        /*2.write hash data to buffer */
        sal_memset(&acc_data, 0, sizeof(PeCpuAccessHashWdata_m));
        sal_memcpy((uint8*)&acc_data,(uint8*)data,ptbl->entry_size);
        _drv_asw_chip_sram_tbl_write( lchip, PeCpuAccessHashWdata_t, 0, (uint32*)&acc_data);

        /*3. triger  hash search */
        SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,1);
        _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

        /*4. wait status */
        do
        {
            _drv_asw_chip_sram_tbl_read(lchip,  PeCpuAccessHashStatus_t, 0,(uint32*)&acc_status);
        }while(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status) && timeout--);

        if(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status))
        {
            ret = DRV_E_TIME_OUT;
            goto out;
        }
        if(!GetPeCpuAccessHashStatus(V,hitMiss_f,&acc_status))
        {
            ret = DRV_E_NOT_EXIST;
            goto out;
        }

        /*5.Get  hash read data*/
        _drv_asw_chip_sram_tbl_read(lchip,  PeCpuAccessHashRdata_t, 0,(uint32*)&acc_rdata);
        sal_memcpy((uint8*)data,(uint8*)&acc_rdata,ptbl->entry_size);
    }
    else if(tbl_id ==ArlTable_t|| tbl_id==McTable_t)
    {
        CpuSearchCtrl_m acc_req;
        CpuUpdateEntry_m acc_entry;
        CpuSearchStatus_m acc_status;

        /*1. reset  hash write */
        SetCpuSearchCtrl(V,searchMc_f,&acc_req,(tbl_id ==ArlTable_t)?0:1);
        SetCpuSearchCtrl(V,searchStart_f,&acc_req,0);
        SetCpuSearchCtrl(V,searchType_f,&acc_req,0);//lookup by key
        SetCpuSearchCtrl(V,directAddr_f,&acc_req,0);
        _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

        /*2.write hash data to buffer */
        _drv_asw_chip_sram_tbl_write( lchip, CpuUpdateEntry_t, 0, data);

        /*3. triger  hash write */
        SetCpuSearchCtrl(V,searchStart_f,&acc_req,1);
        _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

        /*4. wait status */
        do
        {
            _drv_asw_chip_sram_tbl_read(lchip,  CpuSearchStatus_t, 0,(uint32*)&acc_status);
        }while(!GetCpuSearchStatus(V,searchDone_f,&acc_status) && timeout--);

        if(!GetCpuSearchStatus(V,searchDone_f,&acc_status))
        {
            ret = DRV_E_TIME_OUT;
            goto out;
        }
        if(!GetCpuSearchStatus(V,hitMiss_f,&acc_status))
        {
            ret = DRV_E_NOT_EXIST;
            goto out;
        }
        /*5.Get  hash read data*/
        _drv_asw_chip_sram_tbl_read(lchip,  CpuRdbackEntry_t, 0,(uint32*)&acc_entry);
        sal_memcpy(data,&acc_entry,ptbl->entry_size);
    }
out:
#endif
    DRV_UNLOCK(lchip);
    return ret;

}

int32
drv_asw_chip_hash_dump(uint8 lchip, uint32 tbl_id,uint32 index,  uint32* data)
{
    const tables_info_t *ptbl;
#ifdef MEM_MODEL
    uint8* tbl_data_addr = NULL;
#else
    uint32 timeout = 10000;
#endif

    int32 ret = DRV_E_NONE;
    hdump_entry_t  *p_hdump =( hdump_entry_t  *) data;
    uint8* p_data = (uint8*)p_hdump->data_entry;
    ptbl = &drv_tbls_list[tbl_id];

    if(ptbl->tbl_type != TBL_HASH)
    {
        return DRV_E_INVALID_TBL;
    }
    DRV_LOCK(lchip);
#ifdef MEM_MODEL
    if (p_asw_drv_master->model_en)
    {
        ds_t ds;
        uint16  loop = 0;
        uint32 value = 0;
        p_hdump->next_index = p_hdump->start_index?p_hdump->start_index:0;
        p_hdump->valid_num = 0;
        while(loop++ < p_hdump->entry_num)
        {
            _drv_asw_chip_sram_tbl_read(lchip, tbl_id, index, data);
            if(tbl_id >=XlateMacVlanKey_t && tbl_id<=XlateMacKey0_t)
            {
                value = GetXlateMacVlanKey(V,valid_f, &ds);
            }
            else
            {
                value = GetArlTable(V,state_f, &ds);
            }

            if (value)
            {
                tbl_data_addr = (uint8*)p_hdump->data_entry+ ptbl->entry_size*p_hdump->valid_num;
                sal_memcpy(p_data,tbl_data_addr,ptbl->entry_size);
                p_data += ptbl->entry_offset;
                p_hdump->valid_num++;
            }
            p_hdump->next_index += p_hdump->entry_num;
        }
    }
#else
    if(tbl_id >=XlateMacVlanKey_t && tbl_id<=XlateMacKey0_t)
    {
        PeCpuAccessHashReq_m acc_req;
        PeCpuAccessHashStatus_m acc_status;
        ds_t  ds;
        uint16  loop = 0;
        sal_memset(ds,0,sizeof(ds));
        p_hdump->next_index = p_hdump->start_index ? p_hdump->start_index:0;
        p_hdump->valid_num = 0;
        while(loop++ < p_hdump->entry_num)
        {
            /*1. reset  hash read */
            SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,0);
            SetPeCpuAccessHashReq(V,searchType_f,&acc_req,2);//search next valid from last search address
            SetPeCpuAccessHashReq(V,directAddr_f,&acc_req,p_hdump->next_index);
            _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

            /*2. triger  hash read */
            SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,1);
            _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

            /*3. wait status */
            do
            {
                _drv_asw_chip_sram_tbl_read(lchip,  PeCpuAccessHashStatus_t, 0,(uint32*)&acc_status);
            }while(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status) && timeout--);

            if(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status))
            {
                ret = DRV_E_TIME_OUT;
                break;
            }
            if((!GetPeCpuAccessHashStatus(V,hitMiss_f,&acc_status)) || ((p_hdump->next_index) > 255))
            {
                p_hdump->next_index = 0;
                ret = DRV_E_NONE;
                break;
            }
            /*4.get table index*/
            _drv_asw_chip_sram_tbl_read(lchip,  PeCpuAccessHashAddr_t, 0,(uint32*)&ds);
            p_hdump->next_index = GetPeCpuAccessHashAddr(V,tablePtr_f,&ds) +1;

            /*5.Get  hash read */
            _drv_asw_chip_sram_tbl_read(lchip,  PeCpuAccessHashRdata_t, 0,(uint32*)p_data);
            p_data += ptbl->entry_size;
            p_hdump->valid_num++;
        }
    }
    else if(tbl_id ==ArlTable_t|| tbl_id==McTable_t)
    {
        CpuSearchCtrl_m acc_req;
        CpuSearchStatus_m acc_status;
        ds_t  ds;
        uint16  loop = 0;

        p_hdump->next_index = p_hdump->start_index ? p_hdump->start_index:0;
        p_hdump->valid_num = 0;
        while(loop++ < p_hdump->entry_num)
        {
            /*1. reset  hash write */
            SetCpuSearchCtrl(V,searchMc_f,&acc_req,(tbl_id ==ArlTable_t)?0:1);
            SetCpuSearchCtrl(V,searchStart_f,&acc_req,0);
            SetCpuSearchCtrl(V,searchType_f,&acc_req,2);//lookup by key
            SetCpuSearchCtrl(V,directAddr_f,&acc_req, p_hdump->next_index);
            _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

            /*3. triger  hash write */
            SetCpuSearchCtrl(V,searchStart_f,&acc_req,1);
            _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

            /*4. wait status */
            do
            {
                _drv_asw_chip_sram_tbl_read(lchip,  CpuSearchStatus_t, 0,(uint32*)&acc_status);
            }while(!GetCpuSearchStatus(V,searchDone_f,&acc_status) && timeout--);

            if(!GetCpuSearchStatus(V,searchDone_f,&acc_status))
            {
                ret = DRV_E_TIME_OUT;
                break;
            }
            if((!GetCpuSearchStatus(V,hitMiss_f,&acc_status)) || ((tbl_id == ArlTable_t) ? (p_hdump->next_index > 8255):(p_hdump->next_index >511)))
            {
                p_hdump->next_index = 0;
                ret = DRV_E_NONE;
                break;
            }
            /*4.get table index*/
            _drv_asw_chip_sram_tbl_read(lchip,  CpuSearchAddr_t, 0,(uint32*)&ds);
            p_hdump->next_index = GetCpuSearchAddr(V,tablePtr_f,&ds) + 1;
            /*5.Get  hash read data*/

            _drv_asw_chip_sram_tbl_read(lchip,  CpuRdbackEntry_t, 0,(uint32*)p_data);
            p_data += ptbl->entry_size;
            p_hdump->valid_num++;
        }
    }
#endif
    DRV_UNLOCK(lchip);
    return ret;

}

int32
drv_asw_chip_hash_read(uint8 lchip, uint32 tbl_id, uint32 index, uint32*data)
{
    const tables_info_t *ptbl;
#ifndef MEM_MODEL
    uint32 timeout = 10000;
#endif
    int32 ret = DRV_E_NONE;

    ptbl = &drv_tbls_list[tbl_id];

    if(ptbl->tbl_type != TBL_HASH)
    {
        return DRV_E_INVALID_TBL;
    }
    DRV_LOCK(lchip);
#ifdef MEM_MODEL
    if (p_asw_drv_master->model_en)
    {
        _drv_asw_chip_sram_tbl_read(lchip, tbl_id, index, data);
    }
#else
    sal_printf("read hash table tbl_id %d index %d\n", tbl_id, index);
    if(tbl_id >=XlateMacVlanKey_t && tbl_id <= XlateMacKey0_t )
    {
        PeCpuAccessHashReq_m acc_req;
        PeCpuAccessHashStatus_m acc_status;
        PeCpuAccessHashRdata_m  acc_rdata;
        uint8 key_type = 0;

        /*1. reset  hash read */
        SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,0);
        SetPeCpuAccessHashReq(V,searchType_f,&acc_req,4);//lookup by key
        SetPeCpuAccessHashReq(V,directAddr_f,&acc_req,index);
        if (XlateCvlanKey_t == tbl_id)
        {
           key_type = 6;
        }
        else if (XlateSvlanKey_t == tbl_id)
        {
            key_type = 4;
        }
        else if (XlateDoubleVlanKey_t == tbl_id)
        {
            key_type = 5;
        }
        else if (XlateIpv4Key_t == tbl_id)
        {
            key_type = 2;
        }
        else if (XlateIpv6Key_t == tbl_id)
        {
            key_type = 3;
        }
        else if (XlateMacKey_t == tbl_id)
        {
            key_type = 1;
        }
        else if (VlanHashView9_t == tbl_id)
        {
            key_type = 9;
        }
        else if (XlateMacKey0_t == tbl_id)
        {
            key_type = 10;
        }
        SetPeCpuAccessHashReq(V,keyType_f,&acc_req,key_type);
        _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

        /*2. triger  hash search */
        SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,1);
        _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

        /*3. wait status */
        do
        {
            _drv_asw_chip_sram_tbl_read(lchip,  PeCpuAccessHashStatus_t, 0,(uint32*)&acc_status);
        }while(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status) && timeout--);

        if(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status))
        {
            ret = DRV_E_TIME_OUT;
            goto out;
        }

        /*5.Get  hash read data*/
        _drv_asw_chip_sram_tbl_read(lchip,  PeCpuAccessHashRdata_t, 0,(uint32*)&acc_rdata);
        sal_memcpy((uint8*)data,(uint8*)&acc_rdata,ptbl->entry_size);
    }
    else if(tbl_id ==ArlTable_t|| tbl_id==McTable_t)
    {
        CpuSearchCtrl_m acc_req;
        CpuUpdateEntry_m acc_entry;
        CpuSearchStatus_m acc_status;

        /*1. reset  hash write */
        SetCpuSearchCtrl(V,searchMc_f,&acc_req,(tbl_id ==ArlTable_t)?0:1);
        SetCpuSearchCtrl(V,searchStart_f,&acc_req,0);
        SetCpuSearchCtrl(V,searchType_f,&acc_req,4);//looku by key
        SetCpuSearchCtrl(V,directAddr_f,&acc_req,index);
        _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

        /*2. triger  hash write */
        SetCpuSearchCtrl(V,searchStart_f,&acc_req,1);
        _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

        /*4. wait status */
        do
        {
            _drv_asw_chip_sram_tbl_read(lchip,  CpuSearchStatus_t, 0,(uint32*)&acc_status);
        }while(!GetCpuSearchStatus(V,searchDone_f,&acc_status) && timeout--);

        if(!GetCpuSearchStatus(V,searchDone_f,&acc_status))
        {
            ret = DRV_E_TIME_OUT;
            goto out;
        }
        /*5.Get  hash read data*/
        _drv_asw_chip_sram_tbl_read(lchip,  CpuRdbackEntry_t, 0,(uint32*)&acc_entry);
        sal_memcpy(data,&acc_entry,ptbl->entry_size);
    }
out:
#endif
    DRV_UNLOCK(lchip);
    return ret;

}

int32
drv_asw_chip_hash_write(uint8 lchip, uint32 tbl_id, uint32 index, uint32*data)
{
    const tables_info_t *ptbl;
#ifndef MEM_MODEL
    uint32 timeout = 10000;
#endif
    int32 ret = DRV_E_NONE;

    ptbl = &drv_tbls_list[tbl_id];

    if(ptbl->tbl_type != TBL_HASH)
    {
        return DRV_E_INVALID_TBL;
    }
    DRV_LOCK(lchip);
#ifdef MEM_MODEL
    if (p_asw_drv_master->model_en)
    {
        _drv_asw_chip_sram_tbl_read(lchip, tbl_id, index, data);
    }
#else
    if(tbl_id >=XlateMacVlanKey_t && tbl_id <= XlateMacKey0_t )
    {
        PeCpuAccessHashReq_m acc_req;
        PeCpuAccessHashWdata_m acc_data;
        PeCpuAccessHashStatus_m acc_status;
        uint8 key_type = 0;

        /*1. reset  hash read */
        SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,0);
        SetPeCpuAccessHashReq(V,searchType_f,&acc_req,6);//lookup by key
        SetPeCpuAccessHashReq(V,directAddr_f,&acc_req,0);
        if (XlateCvlanKey_t == tbl_id)
        {
           key_type = 6;
        }
        else if (XlateSvlanKey_t == tbl_id)
        {
            key_type = 4;
        }
        else if (XlateDoubleVlanKey_t == tbl_id)
        {
            key_type = 5;
        }
        else if (XlateIpv4Key_t == tbl_id)
        {
            key_type = 2;
        }
        else if (XlateIpv6Key_t == tbl_id)
        {
            key_type = 3;
        }
        else if (XlateMacKey_t == tbl_id)
        {
            key_type = 1;
        }
	  else if (VlanHashView9_t == tbl_id)
        {
            key_type = 9;
        }
        else if (XlateMacKey0_t == tbl_id)
        {
            key_type = 10;
        }
        SetPeCpuAccessHashReq(V,keyType_f,&acc_req,key_type);
        _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

        /*2.write hash data to buffer */
        sal_memset(&acc_data, 0, sizeof(PeCpuAccessHashWdata_m));
        sal_memcpy((uint8*)&acc_data,(uint8*)data,ptbl->entry_size);
        _drv_asw_chip_sram_tbl_write( lchip, PeCpuAccessHashWdata_t, 0, (uint32*)&acc_data);

        /*3. triger  hash search */
        SetPeCpuAccessHashReq(V,searchStart_f,&acc_req,1);
        _drv_asw_chip_sram_tbl_write(lchip,  PeCpuAccessHashReq_t, 0,(uint32*)&acc_req);

        /*4. wait status */
        do
        {
            _drv_asw_chip_sram_tbl_read(lchip,  PeCpuAccessHashStatus_t, 0,(uint32*)&acc_status);
        }while(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status) && timeout--);

        if(!GetPeCpuAccessHashStatus(V,searchDone_f,&acc_status))
        {
            ret = DRV_E_TIME_OUT;
            goto out;
        }
    }
    else if(tbl_id ==ArlTable_t|| tbl_id==McTable_t)
    {
        CpuSearchCtrl_m acc_req;
        CpuSearchStatus_m acc_status;

        /*1. reset  hash write */
        SetCpuSearchCtrl(V,searchMc_f,&acc_req,(tbl_id ==ArlTable_t)?0:1);
        SetCpuSearchCtrl(V,searchStart_f,&acc_req,0);
        SetCpuSearchCtrl(V,searchType_f,&acc_req,0);//looku by key
        SetCpuSearchCtrl(V,directAddr_f,&acc_req,0);
        _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

        /*2.write hash data to buffer */
        _drv_asw_chip_sram_tbl_write( lchip, CpuUpdateEntry_t, 0, data);

        /*3. triger  hash write */
        SetCpuSearchCtrl(V,searchStart_f,&acc_req,1);
        _drv_asw_chip_sram_tbl_write(lchip,  CpuSearchCtrl_t, 0,(uint32*)&acc_req);

        /*4. wait status */
        do
        {
            _drv_asw_chip_sram_tbl_read(lchip,  CpuSearchStatus_t, 0,(uint32*)&acc_status);
        }while(!GetCpuSearchStatus(V,searchDone_f,&acc_status) && timeout--);

        if(!GetCpuSearchStatus(V,searchDone_f,&acc_status))
        {
            ret = DRV_E_TIME_OUT;
            goto out;
        }
    }
out:
#endif
    DRV_UNLOCK(lchip);
    return ret;

}

/**
 @brief The function write table data to a sram memory location
*/
int32
drv_asw_chip_mask_tbl_write(uint8 lchip,  uint32 tbl_id, uint32 index, uint32* data)
{
    int32 ret;
    const tables_info_t *ptbl;
    addrs_t start_data_addr[2] = { 0};
    uint32 mask_tbl_idx = 0;
    uint32 entry_size = 0;
    mask_tbl_entry_t *pe = (mask_tbl_entry_t*)data;

    if(p_asw_drv_master->io_wr_dis[lchip])
    {
        return DRV_E_NONE;
    }

    DRV_PTR_VALID_CHECK(data);
    ptbl = &drv_tbls_list[tbl_id];
    entry_size = ptbl->entry_size;
    switch(tbl_id)
    {
        case UdfCam_t:
            if (index >= ptbl->entry_num)
            {
                DRV_DBG_INFO("\nERROR chip-0x%x, tbl-0x%x, index-0x%x exceeds the max_index-0x%x.\n", lchip, tbl_id, index, ptbl->entry_num);
                return DRV_E_EXCEED_MAX;
            }
            mask_tbl_idx = index + ptbl->entry_num;
            start_data_addr[0] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * ptbl->entry_offset;
            start_data_addr[1] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + mask_tbl_idx * ptbl->entry_offset;
            break;
        case IvmXReg_t:
            start_data_addr[0] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * ptbl->entry_offset;
            ptbl = &drv_tbls_list[IvmXMaskReg_t];
            start_data_addr[1] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * ptbl->entry_offset;
            break;
        case Key160MacView0_t: //key160_mac_view0
        case Key160MacudfView0_t: //key160_macudf_view0
        case Key160EthudfView0_t: //key160_ethudf_view0
        case Key160IpView0_t: //key160_ip_view0
        case Key320MacipudfView0_t: //key320_macipudf_view0
        case Key320IpudfView0_t: //Key320_ipudf_view0
        case Key640Macipv6View0_t:
        case Key320Ipv6View0_t: //Key320_ipv6_view0
        case Key640Macipv6udfView0_t: //Key640_macipv6udf_view0
            /* [31:30..][[29:25][24:0] */
            /* [opType][Tab ID/lkup level ][ index] opType:0-physical table; 1-logic table (lkup level);*/
            {
                if( index >= ptbl->entry_num)
                {/*1/2 entries data;1/2 entries mask*/
                    return DRV_E_EXCEED_MAX;
                }
                mask_tbl_idx = index + ptbl->entry_num;
                start_data_addr[0] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * DRV_ACL_MASK_OFFSET;
                start_data_addr[1] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + mask_tbl_idx * DRV_ACL_MASK_OFFSET;
            }
            break;
        default:
            return DRV_E_INVALID_TBL;
    }

    DRV_LOCK(lchip);
    ret = drv_asw_chip_write(lchip, start_data_addr[0], pe->data_entry, entry_size);
    for (index=0; index<ptbl->entry_size/4; index++)
    {
        pe->mask_entry[index]= ~pe->mask_entry[index];
    }
    ret = ret?ret:drv_asw_chip_write(lchip, start_data_addr[1], pe->mask_entry, ptbl->entry_size);
    if (ret < 0)
    {
        DRV_UNLOCK(lchip);
        return ret;
    }
    DRV_UNLOCK(lchip);
    return ret;
}

/**
 @brief The function read table data from a sram memory location
*/
int32
drv_asw_chip_mask_tbl_read(uint8 lchip, uint32 tbl_id, uint32 index, uint32* data)
{
    const tables_info_t *ptbl;
    addrs_t start_data_addr[2] = {0};
    uint32 mask_tbl_idx = 0;
    uint32 entry_size = 0;
    mask_tbl_entry_t *pe = (mask_tbl_entry_t*)data;

    DRV_PTR_VALID_CHECK(data);
    ptbl = &drv_tbls_list[tbl_id];

    entry_size = ptbl->entry_size;
    switch(tbl_id)
    {
        case UdfCam_t:
            if (index >= ptbl->entry_num)
            {
                DRV_DBG_INFO("\nERROR chip-0x%x, tbl-0x%x, index-0x%x exceeds the max_index-0x%x.\n", lchip, tbl_id, index, ptbl->entry_num);
                return DRV_E_EXCEED_MAX;
            }
            mask_tbl_idx = index + ptbl->entry_num;
            start_data_addr[0] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * ptbl->entry_offset;
            start_data_addr[1] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + mask_tbl_idx * ptbl->entry_offset;
            break;
        case IvmXReg_t:
            start_data_addr[0] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * ptbl->entry_offset;
            ptbl = &drv_tbls_list[IvmXMaskReg_t];
            start_data_addr[1] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * ptbl->entry_offset;
            break;
        case Key160MacView0_t: //key160_mac_view0
        case Key160MacudfView0_t: //key160_macudf_view0
        case Key160EthudfView0_t: //key160_ethudf_view0
        case Key160IpView0_t: //key160_ip_view0
        case Key320MacipudfView0_t: //key320_macipudf_view0
        case Key320IpudfView0_t: //Key320_ipudf_view0
        case Key640Macipv6View0_t:
        case Key320Ipv6View0_t: //Key320_ipv6_view0
        case Key640Macipv6udfView0_t: //Key640_macipv6udf_view0
            /* [31:30..][[29:25][24:0] */
            /* [opType][Tab ID/lkup level ][ index] opType:0-physical table; 1-logic table (lkup level);*/
            {
                if( index >= ptbl->entry_num)
                {/*1/2 entries data;1/2 entries mask*/
                    return DRV_E_EXCEED_MAX;
                }
                mask_tbl_idx = index + ptbl->entry_num;
                start_data_addr[0] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * DRV_ACL_MASK_OFFSET;
                start_data_addr[1] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + mask_tbl_idx * DRV_ACL_MASK_OFFSET;
            }
            break;
        default:
            return DRV_E_INVALID_TBL;
    }
    DRV_LOCK(lchip);
    drv_asw_chip_read(lchip, start_data_addr[0], pe->data_entry, entry_size);
    drv_asw_chip_read(lchip, start_data_addr[1], pe->mask_entry, ptbl->entry_size);
    for (index=0; index<ptbl->entry_size/4; index++)
    {
        pe->mask_entry[index] = ~pe->mask_entry[index];
    }
    DRV_UNLOCK(lchip);
    return DRV_E_NONE;
}

int32
drv_asw_chip_mask_tbl_delete(uint8 lchip, uint32 tbl_id, uint32 index, uint32* data)
{
    int32 ret;
    const tables_info_t *ptbl;
    addrs_t start_data_addr[2] = {0};
    uint32 mask_tbl_idx = 0;
    uint32 entry_size = 0;
    ds_t  tbl_data = {0};
    ds_t  tbl_mask = {0};

    ptbl = &drv_tbls_list[tbl_id];
    entry_size = ptbl->entry_size;
    switch(tbl_id)
    {
        case UdfCam_t:
            if (index >= ptbl->entry_num)
            {
                DRV_DBG_INFO("\nERROR chip-0x%x, tbl-0x%x, index-0x%x exceeds the max_index-0x%x.\n", lchip, tbl_id, index, ptbl->entry_num);
                return DRV_E_EXCEED_MAX;
            }
            mask_tbl_idx = index + ptbl->entry_num;
            start_data_addr[0] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * ptbl->entry_offset;
            start_data_addr[1] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + mask_tbl_idx * ptbl->entry_offset;
            break;
        case IvmXReg_t:
            start_data_addr[0] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * ptbl->entry_offset;
            ptbl = &drv_tbls_list[IvmXMaskReg_t];
            start_data_addr[1] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * ptbl->entry_offset;
            break;
        case Key160MacView0_t: //key160_mac_view0
        case Key160MacudfView0_t: //key160_macudf_view0
        case Key160EthudfView0_t: //key160_ethudf_view0
        case Key160IpView0_t: //key160_ip_view0
        case Key320MacipudfView0_t: //key320_macipudf_view0
        case Key320IpudfView0_t: //Key320_ipudf_view0
        case Key640Macipv6View0_t:
        case Key320Ipv6View0_t: //Key320_ipv6_view0
        case Key640Macipv6udfView0_t: //Key640_macipv6udf_view0
            /* [31:30..][[29:25][24:0] */
            /* [opType][Tab ID/lkup level ][ index] opType:0-physical table; 1-logic table (lkup level);*/
            {
                if( index >= ptbl->entry_num)
                {/*1/2 entries data;1/2 entries mask*/
                    return DRV_E_EXCEED_MAX;
                }
                mask_tbl_idx = index + ptbl->entry_num;
                start_data_addr[0] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + index * DRV_ACL_MASK_OFFSET;
                start_data_addr[1] = g_blk_info[ptbl->blk_id].addr_base + ptbl->addrs[0] + mask_tbl_idx * DRV_ACL_MASK_OFFSET;
            }
            break;
        default:
            return DRV_E_INVALID_TBL;
    }

    DRV_LOCK(lchip);
    ret = drv_asw_chip_write(lchip, start_data_addr[0], (uint32*)&tbl_data, entry_size);
    ret = ret?ret:drv_asw_chip_write(lchip, start_data_addr[1], (uint32*)&tbl_mask, ptbl->entry_size);
    if (ret < 0)
    {
        DRV_UNLOCK(lchip);
        return ret;
    }
    DRV_UNLOCK(lchip);
    return ret;
}
